﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Windows.Media.Imaging;
using System.Xml.Linq;
using AutoLoL.Entities;
using AutoLoL.Logic.Parsers;
using AutoLoL.Logic.Utils;
using AutoLoL.Shared;

namespace AutoLoL.Logic.Repositories
{
    public class LocalMasteryRepository : IMasteryRepository
    {
        private Dictionary<string, ReadOnlyCollection<MasteryBase>> _masteryData;

        public LocalMasteryRepository()
        {
        }

        public MasteryBase GetMasteryById(int masteryId)
        {
            if (_masteryData == null)
            {
                LoadMasteryData();
            }

            foreach (ReadOnlyCollection<MasteryBase> tree in _masteryData.Values)
            {
                MasteryBase mastery = tree.Where(c => c.MasteryId == masteryId).SingleOrDefault();

                if (mastery != null)
                {
                    return mastery;
                }
            }

            return null;
        }

        public MasteryBuild GetMasteryBuild()
        {
            if (_masteryData == null)
            {
                LoadMasteryData();
            }

            MasteryBuild masteryBuild = new MasteryBuild();

            List<MasteryTree> masteryTrees = new List<MasteryTree>();

            foreach (string treeName in _masteryData.Keys)
            {
                MasteryTree masteryTree = new MasteryTree(treeName);
                masteryTree.MasteryBuild = masteryBuild;

                List<MasteryValue> masteries = new List<MasteryValue>();
                foreach (MasteryBase mastery in _masteryData[treeName])
                {
                    MasteryValue masteryValue = new MasteryValue(mastery);
                    masteryValue.MasteryTree = masteryTree;
                    masteries.Add(masteryValue);
                }

                masteryTree.MasteryValues = masteries.ToArray();
                masteryTrees.Add(masteryTree);
            }

            masteryBuild.MasteryTrees = masteryTrees.ToArray();
            return masteryBuild;
        }

        private void LoadMasteryData()
        {
            if (File.Exists(Constants.MASTERIES_XML_FILE))
            {
                Dictionary<string, ReadOnlyCollection<MasteryBase>> masteryData = new Dictionary<string, ReadOnlyCollection<MasteryBase>>();

                XDocument masteriesDoc = XDocument.Load(Constants.MASTERIES_XML_FILE);
                foreach (XElement treeElement in masteriesDoc.Root.Elements("tree"))
                {
                    string treeName = treeElement.Attribute("name").Value;

                    List<MasteryBase> masteries = new List<MasteryBase>();
                    Dictionary<MasteryBase, int> prerequisiteMapping = new Dictionary<MasteryBase, int>();

                    int rowIndex = 0;
                    foreach (XElement rowElement in treeElement.Elements("row"))
                    {
                        // Parse tree
                        int pointsToActivate = int.Parse(rowElement.Attribute("required").Value);

                        foreach (XElement masteryElement in rowElement.Elements("mastery"))
                        {
                            int masteryId = int.Parse(masteryElement.Element("id").Value);
                            int max = int.Parse(masteryElement.Element("max").Value);
                            int column = int.Parse(masteryElement.Element("column").Value);
                            string name = masteryElement.Element("name").Value;
                            string icon = masteryElement.Element("icon").Value;

                            XElement descriptionElement = masteryElement.Element("descriptions");
                            XElement[] descriptionElements = descriptionElement.Elements("description").ToArray();
                            string[] descriptions = new string[descriptionElements.Length];
                            for (int i = 0; i < descriptionElements.Length; i++)
                            {
                                descriptions[i] = descriptionElements[i].Attribute("description").Value;
                            }

                            MasteryBase mastery = new MasteryBase();
                            mastery.MasteryId = masteryId;
                            mastery.MaximumRank = max;
                            mastery.PointsToActivate = pointsToActivate;
                            mastery.Row = rowIndex;
                            mastery.Column = column;
                            mastery.Name = name;
                            mastery.Descriptions = descriptions;

                            mastery.IconBitmapImage = ImageParser.FileToBitmapImage(Path.Combine(Constants.MASTERIES_DIRECTORY, icon));
                            mastery.IconBitmapImageDisabled = ImageParser.BitmapImageToGreyScale(mastery.IconBitmapImage);

                            if (masteryElement.Element("prereq") != null)
                            {
                                prerequisiteMapping.Add(mastery, int.Parse(masteryElement.Element("prereq").Value));
                            }

                            masteries.Add(mastery);
                        }

                        rowIndex++;
                    }

                    // Prerequisites
                    foreach (MasteryBase mastery in prerequisiteMapping.Keys)
                    {
                        int prerequisiteId = prerequisiteMapping[mastery];
                        MasteryBase prerequisiteMastery = masteries.Where(c => c.MasteryId == prerequisiteId).Single();
                        mastery.Prerequisite = prerequisiteMastery;
                    }

                    // Save collection
                    masteryData.Add(treeName, new ReadOnlyCollection<MasteryBase>(masteries));
                }

                _masteryData = masteryData;
            }
        }
    }
}
